﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  MeetingReminder.cs
//    
// Abstract:
//
//  Workflow application for controlling the callflow of a
//  reminder for a meeting.
//  
//--

using System;
using System.Globalization;
using System.Workflow.Activities;
using Microsoft.EnhancedReminders.Dispatcher.Workflow;
using Microsoft.OfficeCommunicationsServer.Applications.Common;
using Microsoft.Rtc.Workflow.Activities;
using Microsoft.Speech.Synthesis;
using Microsoft.Speech.Recognition;

namespace Microsoft.EnhancedReminders.Dispatcher.Workflow
{
    /// <summary>
    /// SequentialWorkflow for controlling the callflow for a meeting reminder.
    /// </summary>
    public sealed partial class MeetingReminder: SequentialWorkflowActivity
    {
        private CalendarNotificationItem _message;
        private NotificationResult _result;

        /// <summary>
        /// ctor.
        /// </summary>
        public MeetingReminder()
        {
            InitializeComponent();
            readItPrompt.MainPrompt.AppendText(PromptResources.ReadIt_MainPrompt);
        }

        /// <summary>
        /// Get or set the NotificationItem to be delivered. This is intended
        /// to be used as an input parameter.
        /// </summary>
        public CalendarNotificationItem Message
        {
            get
            {
                return _message;
            }
            set
            {
                _message = value;

                getPin.Notification = value;
                _result = new NotificationResult(_message, NotificationResultStatus.Error,
                    NotificationChannelType.None);
            }
        }

        /// <summary>
        /// Get or set the NotificationResult from the attempt to deliver
        /// the notification item. This is intended to be accessed as a
        /// return value.
        /// </summary>
        public NotificationResult MessageResult
        {
            get
            {
                return _result;
            }
        }

        /// <summary>
        /// Returns the base path to the Dispatcher assemblies.
        /// </summary>
        public string BasePath
        {
            get
            {
                return System.IO.Path.GetDirectoryName(this.GetType().Assembly.Location) + "\\";
            }
        }

        /// <summary>
        /// Set up the prompts for the meeting QA
        /// </summary>
        private void AskMeetingTurnStarting(object sender, SpeechTurnStartingEventArgs e)
        {
            Logger.WriteTraceInformation(Message.Context, "Workflow: Outputting notification.");

            // Only set the prompts and grammars if no grammars have been set yet; TurnStarting is called
            // every time the prompt speaks and we don't need to reset these fields every time.
            if (askMeeting.Grammars.Count == 0)
            {
                MeetingNotificationItem meeting = Message as MeetingNotificationItem;
                askMeeting.MainPrompt.ClearContent();

                if (meeting != null)
                {
                    askMeeting.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_MainPrompt_1_Meeting); // "You have a meeting organized by
                    askMeeting.MainPrompt.AppendText(meeting.NotificationOriginator);
                }
                else
                {
                    askMeeting.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_MainPrompt_1_Appointment); // "You have an appointment
                }

                askMeeting.MainPrompt.AppendSsmlMarkup(DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, _message.StartTime, new SsmlTimeSpanFormatter()));

                if (!string.IsNullOrEmpty(Message.Message))
                {
                    askMeeting.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeeting_MainPrompt_Subject); // "Subject - "
                    askMeeting.MainPrompt.AppendText(Message.Message);
                }

                if (!string.IsNullOrEmpty(Message.Location))
                {
                    askMeeting.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_MainPrompt_Location); // "Location - "
                    askMeeting.MainPrompt.AppendText(Message.Location);
                }

                askMeeting.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_MainPrompt_2); // "Would you like to REPEAT or DISMISS?

                askMeeting.DtmfGrammars.Add(new Grammar(BasePath + Helpers.GetSetting<string>("DtmfGrammar",null), "Meeting"));

                askMeeting.Grammars.Add(new Grammar(BasePath + Helpers.GetSetting<string>("VoiceGrammar",null), "Meeting"));
                askMeetingHelp.Grammar = new Grammar(BasePath + Helpers.GetSetting<string>("VoiceGrammar",null), "MeetingHelp");
                askMeetingRepeat.Grammar = new Grammar(BasePath + Helpers.GetSetting<string>("VoiceGrammar",null), "MeetingRepeat");
                askMeetingRepeat.DtmfGrammar = new Grammar(BasePath + Helpers.GetSetting<string>("DtmfGrammar",null), "MeetingRepeat");

                askMeeting.Prompts.HelpPrompt.AppendAudio(BasePath + PromptAudio.Meeting_HelpPrompt); // "To hear this reminder again, say REPEAT, or press 8.  To dismiss, say DISMISS or press 7.

                askMeeting.Prompts.RepeatPrompt.AppendAudio(BasePath + PromptAudio.Meeting_RepeatPrompt); // "OK.  Here it is again.
                askMeeting.Prompts.RepeatPrompt.AppendPromptBuilder(askMeeting.MainPrompt);

                askMeeting.Prompts.SilencePrompt.AppendAudio(BasePath + PromptAudio.Meeting_SilencePrompt); // "You can say REPEAT or DISMISS.

                askMeeting.Prompts.EscalatedSilencePrompt.AppendAudio(BasePath + PromptAudio.Meeting_EscalatedSilencePrompt); // "To hear this reminder again, say REPEAT, or press 8.  To dismiss, say DISMISS or press 7.

                askMeeting.Prompts.NoRecognitionPrompt.AppendAudio(BasePath + PromptAudio.Meeting_NoRecognitionPrompt); // "Sorry, I missed that.

                askMeeting.Prompts.EscalatedNoRecognitionPrompt.AppendAudio(BasePath + PromptAudio.Meeting_EscalatedNoRecognitionPrompt); // "I didn’t get that either.  
            }
        }

        #region Code Conditions
        private void IsResponseReadIt(object sender, ConditionalEventArgs e)
        {
            e.Result = askMeeting.RecognitionResult.Semantics.Value.ToString() == "ReadIt" && 
                _message.HasBody;
        }

        private void IsResponseDismiss(object sender, ConditionalEventArgs e)
        {
            e.Result = askMeeting.RecognitionResult.Semantics.Value.ToString() == "Dismiss";
        }
        #endregion

        /// <summary>
        /// This should be called after we've verified the user's PIN. Verification
        /// of a PIN means that this notification was successful.
        /// </summary>
        private void SetNotificationResult(object sender, EventArgs e)
        {
            Logger.WriteTraceInformation(Message.Context, "Workflow: User has entered a valid PIN.");
            _result.Status = NotificationResultStatus.Success;
        }

        /// <summary>
        /// Called when the user says "dismiss." Sets the audio for the dismiss prompt.
        /// </summary>
        private void DismissTurnStarting(object sender, SpeechTurnStartingEventArgs e)
        {
            Logger.WriteTraceInformation(Message.Context, "Workflow: User has dismissed the notification.");
            dismissPrompt.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_Dismiss); // "OK.  I’ve dismissed your reminder.
            dismissPrompt.MainPrompt.AppendAudio(BasePath + PromptAudio.Generic_Goodbye);
        }

        /// <summary>
        /// Called when the user has exceeded the number of no recognition events for the askMeeting QA.
        /// Sets the audio for the goodbye prompt.
        /// </summary>
        private void AskMeetingGoodbyeNoRecoTurnStarting(object sender, SpeechTurnStartingEventArgs e)
        {
            Logger.WriteTraceInformation(Message.Context, "Workflow: User has exceeded maximum number of non-recognitions. Disconnecting call.");
            askMeetingGoodbyeNoReco.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_GoodbyeNoReco);
        }

        /// <summary>
        /// Called when the user has been silent for the maximum number of turns at the askMeeting QA.
        /// Sets the audio for the goodbye prompt.
        /// </summary>
        private void AskMeetingGoodbyeSilenceTurnStarting(object sender, SpeechTurnStartingEventArgs e)
        {
            Logger.WriteTraceInformation(Message.Context, "Workflow: User has exceeded maximum number of silences. Disconnecting call.");
            askMeetingGoodbyeSilence.MainPrompt.AppendAudio(BasePath + PromptAudio.Meeting_GoodbyeSilence);
        }
    }
}
